
#define STRICT
#define WIN32_LEAN_AND_MEAN

#include <Windows.h>
#include <WindowsX.h>
#include <assert.h>

#include "Graphics.h"
#include "DirectInput.h"
#include "DirectShow.h"
#include "Game.h"
#include "Sound.h"
#include "Globals.h"
#include "Vector.hpp"
#include"Player.h"
#include<time.h>
#include<random>
#include<conio.h>
#include<iomanip>
// Win32 necessary function prototypes
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR psCmdLine, int nCmdShow);
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void OpenWindow(const char* cszClassName, const char* cszWindowName, int nCmdShow);

bool Initialize(HINSTANCE hInstance, int nCmdShow);
bool Update(HINSTANCE hInstance, int nCmdShow);
bool Draw();

// globals
HWND			hWnd		= NULL;								// handle to the window
Dimensions		g_dimScreen(SCREEN_WIDTH, SCREEN_HEIGHT);		// the width and height of the screen
eMainState		g_State		= GAME;								// holds the main state of the program
Vector<BaseObject*> tempObjects;
Vector<BaseObject*> g_listObjects;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR psCmdLine, int nCmdShow)
{
	Initialize(hInstance, nCmdShow);
	MSG uMsg;
	memset(&uMsg, 0, sizeof(uMsg));

	//CreateTempObjects(tempObjects);

	while(uMsg.message != WM_QUIT)							// loop until either windows or the game engine is told to quit
	{
		while(PeekMessage(&uMsg, NULL, 0, 0, PM_REMOVE))	// translate and dispatch all messages in the message queue
		{
			TranslateMessage(&uMsg);
			DispatchMessage(&uMsg);
		}

		Update(hInstance, nCmdShow);				// updates all aspects of the game, returns false to signify program to quit
		DInput::Engine()->PollDevices();			// gets input from keyboard and mouse
		Draw();										// draw one frame of the game		
	}
	UnregisterClass("D3DWindow", hInstance);
	
	return uMsg.wParam;
}

// initializes all aspects of the game (call other init functions inside here)
bool Initialize(HINSTANCE hInstance, int nCmdShow)
{
	OpenWindow("D3DWindow", "Console Wars!", nCmdShow);			// attempt to open a new window
	if(NULL == hWnd)													// if the window was not initialized properly, quit
		return false;

	RECT rClientRect;
	GetClientRect(hWnd, &rClientRect);									// obtain the actual window's dimensions
	g_dimScreen.width = (int)(rClientRect.right - rClientRect.left);
	g_dimScreen.height = (int)(rClientRect.bottom - rClientRect.top);

	//////////////////// begin initialization of all the aspects of the game engine ////////////////////

	// if any of the initializations failed, return false, signifying that something went wrong
	if(!Graphics::Engine()->Init(hWnd))					
		return false;
	if(!DInput::Engine()->Init(hWnd, hInstance))			
		return false;
	if(!DirectShow::Engine()->Init(hWnd))
		return false;
	if(!Game::Engine()->Init())
		return false;
	/*if(!Sound::Engine()->Init(effectFiles, streamFiles))
		return false;*/

	//////////////////// end initialization of engines ////////////////////

	return true; // if everything initialized fine, return true
}

// determines what to update based on what the state of the game is
// returns true if the program is to continue, and false to quit
bool Update(HINSTANCE hInstance, int nCmdShow)
{
	switch (g_State)
	{
	case MENU:
		//If the mouse is in the right spot and you click the shape
		if(Menu::Engine()->Update(hWnd) && DInput::Engine()->mouseButtonHit(0))
		{
			//change state to game
			g_State=GAME;
		//	Game::Engine()->m_eState=CARD_SELECT;
		}
		break;
	case MOVIE:
		break;
	case GAME:
		Game::Engine()->Update();
		if(DInput::Engine()->keyPressed(DIK_ESCAPE))
			g_State = MENU;
	
	
		/*if(DInput::Engine()->keyPressed(DIK_1)) //Testing button
			Game::Engine()->m_bPlayerSwitch=true;*/

		
		
		break;
	case SHUTDOWN:
		break;
	}


	Sound::Engine()->DoWork();
	return true;
}

bool Draw()
{
	// render the menu if the state is in MENU
	if(g_State == MENU)
		Graphics::Engine()->RenderMenu();

	// render the game if the state is in GAME
	else if(g_State == GAME)
		Graphics::Engine()->RenderGame(g_listObjects,Game::Engine()->m_bDrawBoard);
	
	return true;
}

void OpenWindow(const char* cszWinClassName, const char* cszWindowName, int nCmdShow)
{
	/* Register window class and create window */

	WNDCLASSEX winClass;

	HINSTANCE hInstance = ::GetModuleHandle(NULL);
	assert(NULL != hInstance);
	//HICON hIcon = ::LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));
	//assert(NULL != hIcon);

	winClass.lpszClassName = cszWinClassName;
	winClass.cbSize        = sizeof(WNDCLASSEX);
	winClass.style         = CS_HREDRAW | CS_VREDRAW;
	winClass.lpfnWndProc   = WindowProc;
	winClass.hInstance     = hInstance;
	winClass.hIcon		   = /*hIcon*/NULL;
    winClass.hIconSm	   = /*hIcon*/NULL;
	winClass.hCursor       = ::LoadCursor(NULL, IDC_ARROW);
	winClass.hbrBackground = (HBRUSH)::GetStockObject(BLACK_BRUSH);
	winClass.lpszMenuName  = NULL;
	winClass.cbClsExtra    = 0;
	winClass.cbWndExtra    = 0;

	if (0 == RegisterClassEx(&winClass))
		return;

	hWnd = ::CreateWindowEx(NULL,
							cszWinClassName,
							cszWindowName,
							WS_OVERLAPPEDWINDOW,
							0, 0,
							g_dimScreen.width, g_dimScreen.height,
							NULL, NULL, ::GetModuleHandle(NULL), NULL);

	ShowWindow(hWnd, nCmdShow);
	UpdateWindow(hWnd);
}

LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch(uMsg)
	{
		case WM_CLOSE:
			{
				PostQuitMessage(0);
				break;
			}
	}

	return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
